home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Programming Sound Cards
/
Programming Sound Cards.iso
/
sound_52
/
cfunk.ma
< prev
next >
Wrap
Text File
|
1995-01-01
|
13KB
|
653 lines
#
# compufunk
#
# setup:
# 3 voicelists
# vco 1: bass voice
# Determines overall harmonic structure. Current chord note
# is stored in a global. Melody uses this to improvise off of.
# There are two base forms. Both consist of various bass riffs
# stored as procedural data (coded up). The first form has
# very little improv. The second pieces its riffs together
# in a random fashion.
# vco 2: keyboard reader, maps a key to various changes
# should be plugged into melody player channel at MIDI level
# since various keys may change the melody patches.
# vco 3: melody player, there are a number of melody forms. See
# the key description. The melody follows the bass voice.
# vco 4: optional double of melody code.
#
# various keys cause various transformations.
#
# Idea is to play bass and jam against it with solo instrument.
# melody can be switched in and out, can play duet with it.
#
# harmonic structure:
#
# Two parts
# 1. 8 bar melody lead. Melody plays horns in fifths and
# uses fairly staid melody form.
# 2. 12 bar blues form.
# Harmonic structure is
# E E E E A A E E C D E E
# all minor 7th chords. Suggest using polytonality by
# playing chord notes of minor 7th that is a fifth higher.
#
# key transformations
#
# a key: - force one round of "theme" 8 bar melody lead.
# c key: - melody form 1. dorian/blues pentatonic random melody
# d key: - turn melody generation OFF
# e key: - melody form 2. pentatonic chords
# f key: - melody form 3. "wave" melody, ascending arpeggios
# g key: - melody form 4. fractal melody
# h key: - melody form 5. dorian/polytonal melody (add a 7th sometimes)
# p key: - enable random switches between patches for melody voice.
# o key: - enable random switches between melody forms.
# m key: - make random change on patch for melody - use melody patch set.
# r key: - make random change on patch for melody - use rhythm patch set.
# s key: - turn second melody on (toggle)
#
# constants
#
NOMODES = 4
OCTAVE = 12
FIFTH = 7
PENTA = 5
JAZZMINOR = 7
MAXRHYTHM = 5 # random rhythmic patches to choose from
MAXMEL = 15 # random melody patches to choose from
ACHAR = 0x61
BCHAR = 0x62
CCHAR = 0x63
DCHAR = 0x64
ECHAR = 0x65
FCHAR = 0x66
GCHAR = 0x67
HCHAR = 0x68
ICHAR = 0x69
JCHAR = 0x6a
KCHAR = 0x6b
LCHAR = 0x6c
MCHAR = 0x6d
NCHAR = 0x6e
OCHAR = 0x6f
PCHAR = 0x70
QCHAR = 0x71 # don't use
RCHAR = 0x72
SCHAR = 0x73
# global vars
uchar mode # melody mode
uchar chordbase # fundamental of current chord
uchar pentascale[5]
uchar minorscale[7]
uchar solocount
uchar basemode # bass harmonic/tempo mode
uchar pkey # set if patch change desired
uchar okey # set if mode changes should be automatic
uchar lastnote
uchar solo2on
uchar solopatch
uchar chordProg[12]
# fb01 patch groups
#
uchar fbrhythm[MAXRHYTHM]
uchar fbmelody[MAXMEL]
# functions
# setup fb01 patches to randomly choose from
# all are bank 1
#
riff initpatch()
fbrhythm[0] = 31 # steeldrum
fbrhythm[1] = 32 # timpani
fbrhythm[2] = 22 # xylo
fbrhythm[3] = 43 # snare
fbrhythm[4] = 45 # tomtom
fbmelody[0] = 33
fbmelody[1] = 34
fbmelody[2] = 37
fbmelody[3] = 38
fbmelody[4] = 40
fbmelody[5] = 41
fbmelody[6] = 42
fbmelody[7] = 2
fbmelody[8] = 8
fbmelody[9] = 9
fbmelody[10] = 16
fbmelody[11] = 18
fbmelody[12] = 20
fbmelody[13] = 7
fbmelody[14] = 11
end
riff initHarmony()
chordProg[0] = LE
chordProg[1] = LE
chordProg[2] = LE
chordProg[3] = LE
chordProg[4] = LA
chordProg[5] = LA
chordProg[6] = LE
chordProg[7] = LE
chordProg[8] = LC
chordProg[9] = LD
chordProg[10] = LE
chordProg[11] = LE
end
riff init()
pentascale[0] = 3
pentascale[1] = 5
pentascale[2] = 7
pentascale[3] = 10
pentascale[4] = 12
minorscale[0] = 2
minorscale[1] = 3
minorscale[2] = 5
minorscale[3] = 7
minorscale[4] = 9
minorscale[5] = 10
minorscale[6] = 12
end
riff choosetwo(t1,t2)
if ( mrand() < 127 )
return(t1)
else
return(t2)
end
end
########################################
# base melody fragments
#
# helper function for below b1, simple variation
riff subb1()
LE tq 105
LE te 90
E tq choosetwo(105,100)
LE te 90
D tq choosetwo(105,100)
LE te 90
E tq choosetwo(105,100)
LB te 94
# m2
LE tq choosetwo(110,105)
LE te
E q choosetwo(105,95)
LD tq choosetwo(100,90)
LB te 90
if ( mrand() < 120 )
LD tq 100
LB te 90
else
LA tq 100
LG te 90
end
end
# 2 measures
riff b1(base)
chordbase = base
if ( base == LE && mrand() < 50 )
void subb1()
return(1)
end
if ( mrand() < 50 )
base q mrandrange(115,121)
else
base tq mrandrange(115,117)
base te 90
end
base+12 q 100
base+10 h mrandrange(90,100)
# m2
base q mrandrange(110,117)
base+12 q 100
#
base+10 tq mrandrange(90,110)
base+7 te 100
# m2, b4
base+5 tq 100
if ( mrand() < 100 )
base+3 te 100
else
base+3 te 90
end
end
# similar to b1, but only a measure long
riff b5(base)
chordbase = base
base q 120
base+12 q 100
if ( mrand() < 100 )
base+10 h 100
else
base+10 tq mrandrange(115,100)
base+10 te 90
base+7 q
end
end
# second measure of b1
riff b6(base)
chordbase = base
base q 115
base+12 q 100
base+10 tq 105
base+7 te 100
base+5 tq 100
base+3 te 100
end
# 1 measure
riff b3(base)
chordbase = base
base tq mrandrange(90,115)
base te mrandrange(80,95)
base+12 tq mrandrange(90,105)
base+12 te 85
base+10 te 105
base+12 te 90
base+10 te
base+5 te 105
base+7 te
base+10 te
end
#1 measures
riff b4(base)
chordbase = base
base+12 tq 110
base+12 te 100
base+3 tq 105
base+3 te 100
base+5 tq 110
base+5 te 100
base+7 tq 110
base+7 te 100
end
riff b7(base)
chordbase = base
base tq 110
base te 90
base+3 tq 105
base+3 te 90
base+5 tq 100
base+5 te 107
base+7 tq mrandrange(110,115)
base+7 te 100
end
riff specialB()
chordbase = LC
LC q 110
LC+12 q 100
LC+10 h 95
chordbase = LD
LD q 110
LD+12 q 90
LD+10 tq 105
LD+7 te 100
LD+5 tq 100
LD+3 te 100
end
# end of bass melody fragments
#
riff solotime()
if ( {mrand()%2} == 0 )
return(tq)
else
return(te)
end
end
riff choosethree(t1,t2,t3)
uchar rno
rno = mrand()
if ( rno < 85 )
return(t1)
end
if ( rno < 170 )
return(t2)
end
return(t3)
end
#
# choose a note out of one of the two scales
# add an octave to base to get note up into middle range
#
riff solonote()
uchar index
if ( {solocount % 4} < 2)
return(pentascale[mrand()%PENTA]+ OCTAVE + chordbase)
else
return(minorscale[mrand()%JAZZMINOR] + OCTAVE + chordbase)
end
end
#
# play so many measures of solo melody
#
riff dosolo()
uchar mcount
uchar time
uchar solocount
uchar tcount
uchar nnote
uchar vel
solocount++
if ( mode == 5 )
solopatch = 0
patch 0
end
for ( mcount = 0; mcount < 6; mcount++)
# check to see if random mode changes are
# desired
if ( mcount == 3 && okey )
mode = {mrand() % NOMODES} + 1
end
for ( tcount = 0; tcount < w; )
time = solotime()
if ( mode == 1 )
solonote() time mrandrange(90,115)
else
if ( mode == 2 )
vel = mrandrange(90,120)
nnote = solonote()
if ( mrand() < 150 )
chord nnote,nnote+12,nnote+24 end time + 12
else
chord nnote,nnote+7,nnote+12,nnote+14,nnote+24 end time + 12
end
time = time + 12
else # mode is 3
if ( mode == 3 )
nnote = solonote()
vel = mrandrange(80,110)
nnote s vel
nnote + 2 t vel + 2
nnote + 5 s vel + 4
nnote + 7 t vel + 6
nnote + 12 s vel + 8
nnote + 17 t vel + 10
nnote + 19 s vel + 12
nnote + 24 t vel + 14
else # mode is 4, fractal melody
if ( mode == 4 )
lastnote = mfractal1(lastnote)
vel++
if ( vel > 115 )
vel = 85
end
chordbase+pentascale[lastnote%PENTA]+24 choosethree(s,e,h) vel
else # mode is 5, basemode special melody
if ( mode == 5 )
if ( solopatch != 0 )
patch 0
solopatch = 0
end
nnote = solonote()
time = solotime()
vel = mrandrange(100,120)
chord nnote,nnote+7 end time vel
# mode 6, venture into polytonal up a 5th
else
if ( mrand() < 190 )
nnote = solonote() + 7
else
nnote = solonote()
end
nnote solotime() mrandrange(90,120)
end
end
end
end
end
tcount = tcount + time
end
end
# if pkey set however random changes 1..33
if ( pkey )
solopatch = {mrand() % 32} + 1
patch solopatch
end
end
# first baseform
# not much variation in riffs
#
riff baseform1()
void b1(LE)
void b1(LE)
void b1(LA)
void b1(LE)
if ( mrand() < 200 )
void specialB()
else
void b1(LB)
end
void b1(LE)
end
# in charge of varying the bass melody
#
riff baseform2()
uchar rval
uchar chordindex
uchar lastval
lastval = 1
for ( chordindex = 0; chordindex < 12; chordindex++)
rval = mrand() % 5
# try again if riff number matches, should reduce
# frequency of repeats
if (lastval == rval)
rval = mrand() % 5
end
if ( rval == 1 )
void b3(chordProg[chordindex])
else
if ( rval == 2 )
void b4(chordProg[chordindex])
else
if ( rval == 3 )
void b5(chordProg[chordindex])
else
if ( rval == 4 )
void b6(chordProg[chordindex])
else
void b7(chordProg[chordindex])
end
end
end
end
lastval = rval
end # for
end
######################################################
# VOICELISTS
###################
#
# bass is first voice.
#
# determines harmonic structure.
# The base tone of the current chord is saved by any routines
# called by the "bass" voicelist. Melody generation uses this
# to generate melodic fragments.
#
vco bass
uchar index
uchar firstcall
okey = 0
pkey = 0
mode = 0 # solo starts off
basemode = 1
solocount = 0
lastnote = LE
void init()
void initHarmony()
void initpatch()
firstcall = 1
# now start to play bass variations unless n key is
# typed.
# 'n' means normal form again
for (;;)
# if basemode is set then play 8 bar "line"
if ( basemode )
mode = 5
void b1(LE)
void b1(LG)
void b1(LA)
void b1(LE)
void b1(LE)
void b1(LC)
void b1(LD)
void b1(LE)
mode = 4
basemode = 0
# else normal improv section
else
if ( firstcall )
firstcall = 0
void baseform1()
else
# small percent of normal base playing
if ( mrand() < 10 )
void baseform1()
else
# great deal of improv base playing
void baseform2()
end
end
end
end
end
#
# check the keyboard
# if a char is received turn on the solo channel
# or turnoff the solo if it is playing
#
vco readKey
uchar input
uchar patchVal
#
# check every quarter note
for(;;)
if (misch())
input = mgetch()
if ( input == ACHAR )
void printf("%d\n",1)
basemode = 1
okey = 0
pkey = 0
end
if ( input == CCHAR )
mode = 1
end
if ( input == DCHAR )
mode = 0
end
if ( input == ECHAR )
mode = 2
end
if ( input == FCHAR )
mode = 3
end
if ( input == GCHAR )
mode = 4
end
if ( input == HCHAR )
mode = 6
end
if ( input == PCHAR )
pkey = ~pkey # toggle
void printf("%d\n",pkey)
end
if ( input == OCHAR )
okey = ~okey # toggle
void printf("%d\n",okey)
end
# random change of melody patch
if ( input == MCHAR )
solopatch = fbmelody[mrand()%MAXMEL]-1
patch solopatch
end
# random change to rhythm patch
if ( input == RCHAR )
solopatch = fbrhythm[mrand()%MAXRHYTHM]-1
patch solopatch
void printf("%d\n",patchVal)
end
if ( input == SCHAR )
solo2on = ~solo2on
end
else
REST q
end
end
end
#
# play a solo when mode is non-zero
#
vco solo
for(;;)
if ( mode )
void dosolo()
else
REST w
end
end
end
# optional double of solo voice
#
vco solo2
solo2on = 0
for(;;)
if ( solo2on )
void dosolo()
else
REST w
end
end
end